package com.commissarxiii.loader 
{
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.HTTPStatusEvent;
	import flash.events.IOErrorEvent;
	import flash.events.SecurityErrorEvent;
	import flash.external.ExternalInterface;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	/**
	 * LoaderItem is responsible for loading a file via
	 * a URLLoader instance and passing the loaded data to
	 * a JavaScript callback.
	 * 
	 * @author Benjamin Van Heest
	 * @version 1.0
	 */
	public class LoaderItem extends EventDispatcher
	{
		/**
		 * Url of the file to load
		 */
		private var _url:String;
		/**
		 * Javascript function called when data is loaded
		 */
		private var _jsCallback:String;
		/**
		 * Holds URLLoader instance, used for loading supplied url
		 */
		private var _urlLoader:URLLoader;
		
		/**
		 * Create a new LoaderItem instance.
		 * 
		 * @param	url URL of the file to load
		 * @param	jsCallback JavaScript function to call when data is loaded
		 */
		public function LoaderItem(url:String, jsCallback:String = null) 
		{
			_url = url;
			_jsCallback = jsCallback;
			init();
		}
		
		/**
		 * Initialize LoaderItem.
		 */
		private function init():void
		{
			initializeLoader();
		}
		
		/**
		 * Load specified URL.
		 */
		public function load():void 
		{
			_urlLoader.load(new URLRequest(_url));
		}
		
		/**
		 * Handle complete event from URLLoader. Tries to pass
		 * loaded data to supplied JavaScript callback and re-dispatches
		 * event for further handling.
		 * 
		 * @param	event
		 */
		private function handleComplete(event:Event):void 
		{
			if (ExternalInterface.available)
			{
				ExternalInterface.call(_jsCallback, event.target.data);
			}
			
			disposeLoader();
			
			dispatchEvent(event);
		}
		
		/**
		 * Handle IOError event from URLLoader. Calls the FlashLoader.error
		 * Javascript method and supplies the event text.
		 * 
		 * @param	event
		 */
		private function handleIOError(event:IOErrorEvent):void 
		{
			if (ExternalInterface.available)
			{
				ExternalInterface.call('FlashLoader.error', event.text);
			}
			
			disposeLoader();
			
			dispatchEvent(event);
		}
		
		/**
		 * Handle security error event from URLLoader. Calls the FlashLoader.error
		 * JavaScript method and supplies the event text.
		 * @param	event
		 */
		private function handleSecurityError(event:SecurityErrorEvent):void 
		{
			if (ExternalInterface.available)
			{
				ExternalInterface.call('FlashLoader.error', event.text);
			}
			
			disposeLoader();
			
			dispatchEvent(event);
		}
		
		private function handleHTTPStatus(event:HTTPStatusEvent):void 
		{
			// currently unhandled
		}
		
		/**
		 * Creates a new URLLoader instance and adds required event
		 * listeners.
		 */
		private function initializeLoader():void
		{
			_urlLoader = new URLLoader();
			_urlLoader.addEventListener(Event.COMPLETE, handleComplete);
			_urlLoader.addEventListener(IOErrorEvent.IO_ERROR, handleIOError);
			_urlLoader.addEventListener(HTTPStatusEvent.HTTP_STATUS, handleHTTPStatus);
			_urlLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, handleSecurityError);
		}
		
		/**
		 * Removes URLLoader event listeners and sets the instance to
		 * null for memory management.
		 */
		private function disposeLoader():void
		{
			_urlLoader.removeEventListener(Event.COMPLETE, handleComplete);
			_urlLoader.removeEventListener(IOErrorEvent.IO_ERROR, handleIOError);
			_urlLoader.removeEventListener(HTTPStatusEvent.HTTP_STATUS, handleHTTPStatus);
			_urlLoader.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, handleSecurityError);
			_urlLoader = null;
		}
		
		/**
		 * Returns specified URL.
		 */
		public function get url():String
		{
			return _url;
		}
		
		/**
		 * Returns specified JavaScript callback function.
		 */
		public function get jsCallback():String
		{
			return _jsCallback;
		}
	}

}